
import java.lang.reflect.Method;

public class DEFfunctionConverters {

	static XSLconverter xslConverter = new XSLconverter();
	static int XSLRunVariableIndex = 0;
	static int VariableRunVariableIndex = 0;
	
	static RegexMatcher regexMatcher = new RegexMatcher();
	
	public static String convertLenToXSL(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@LEN(RE1:11)"
		// output: 
		//			<xsl:value-of select="string-length($len0)"/>
		
		String tempLenVariable = getNextTempVariableName("len", 0);
		String returnString = xslConverter.wrapInXSL("string-length(" + tempLenVariable + ")");
		return returnString;
	}

	public static String getLenVariables(String group) {
		// input:
		// 			defStringToConvert = "@LEN(RE1:11)"
		// output: 
		//			<xsl:variable name="len0"><xsl:value-of select="RE[1]/REn_11"/></xsl:variable>
		
		String selection = regexMatcher.getRegexMatch("(?<=\\().+(?=\\))", group); //from after '(' to before ')'
		NewConverter DEFConverter = new NewConverter();
		DEFConverter.convert(selection);
		String result = DEFConverter.resultXSL;
		return wrapAndNameVariable(result, "len");
	}
	
	public static String convertCutToXSL(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@CUT(@DE1:0,1,25)"
		// output: 
		//			<xsl:value-of select="mismo:cOneCut($cut0,1,25)"/>"/>
		
		String mainSelection = regexMatcher.getRegexMatch("(?<=\\().+(?=\\))", defStringToConvert); //from after '(' to before ')'
		String start = regexMatcher.getRegexMatch("(?<=,)[0-9]+(?=,)", mainSelection);
		String end = regexMatcher.getRegexMatch("(?<=,)[0-9]+", regexMatcher.getRegexMatch("(?<=,).+", mainSelection));
		String tempCutVariable = getNextTempVariableName("cut", 0);
		String returnString = xslConverter.wrapInXSL("mismo:cOneCUT(" + tempCutVariable + "," + start + "," + end + ")");
		return returnString;
	}
	
	public static String getCutVariables(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@CUT(@DE1:0,1,25)"
		// output: 
		//			<xsl:variable name="cut0"><xsl:value-of select="DE[1]/DEn_0"/></xsl:variable>
		
		String variableSelection = regexMatcher.getRegexMatch("(?<=\\().+(?=,)", defStringToConvert); //from after '(' to before ')'
		NewConverter DEFConverter = new NewConverter();
		DEFConverter.convert(variableSelection);
		String result = DEFConverter.resultXSL;
		return wrapAndNameVariable(result, "cut");
	}
	
	public static String convertPadrToXSL(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@PADR(10,"@DE1:0",33)"
		// output: 
		//			<xsl:value-of select="mismo:cOnePADR(10,$padr0,33)"/>"/>
		
		String returnString = "";
		String selection = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{4}\\().+", defStringToConvert); //grabs string from start ( to end
		selection = selection.substring(0, selection.length()-1); //gets rid of end )
		String numberOfSpaces = regexMatcher.getRegexMatch("[0-9]+(?=,)", selection);
		String padAsciiRepresentation = regexMatcher.getRegexMatch("(?<=\",)[0-9]+", selection);
		String tempAuxiliaryVariable = getNextTempVariableName("padr", 0);
		returnString = "mismo:cOnePADR(" + numberOfSpaces + "," + tempAuxiliaryVariable + "," + padAsciiRepresentation + ")";
		return xslConverter.wrapInXSL(returnString);
	
	}
	
	public static String getPadrVariables(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@PADR(10,"@DE1:0",33)"
		// output: 
		//			<xsl:variable name="padr0"><xsl:value-of select="DE[1]/DEn_0"/></xsl:variable>
		
		String selection = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{4}\\().+", defStringToConvert); //grabs string from start ( to end
		selection = selection.substring(0, selection.length()-1); //gets rid of end )
		String numberOfSpaces = regexMatcher.getRegexMatch("[0-9]+(?=,)", selection);
		String padAsciiRepresentation = regexMatcher.getRegexMatch("(?<=\",)[0-9]+", selection);
		String auxiliary = regexMatcher.getRegexMatch("(?<=" + numberOfSpaces + ",\").+(?=\"," + padAsciiRepresentation + ")", selection);
		String auxiliaryVariableName = getNextTempVariableName("padr", 1).substring(1); //substring to get rid of $
		NewConverter DEFConverter = new NewConverter();
		DEFConverter.convert(auxiliary);
		String result = DEFConverter.resultVariables + DEFConverter.resultXSL;
		return wrapVariable(result, auxiliaryVariableName);
	}
	
	public static String convertPadlToXSL(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@PADL(10,"@DE1:0",33)"
		// output: 
		//			<xsl:value-of select="mismo:cOnePADL(10,$padl0,33)"/>"/>
		
		String selection = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{4}\\().+", defStringToConvert); //grabs string from start ( to end
		selection = selection.substring(0, selection.length()-1); //gets rid of end )
		String numberOfSpaces = regexMatcher.getRegexMatch("[0-9]+(?=,)", selection);
		String padAsciiRepresentation = regexMatcher.getRegexMatch("(?<=\",)[0-9]+", selection);
		String tempAuxiliaryVariable = getNextTempVariableName("padl", 0);
		String returnString = "mismo:cOnePADL(" + numberOfSpaces + "," + tempAuxiliaryVariable + "," + padAsciiRepresentation + ")";
		return xslConverter.wrapInXSL(returnString);
	
	}
	
	public static String getPadlVariables(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@PADL(10,"@DE1:0",33)"
		// output: 
		//			<xsl:variable name="padl0"><xsl:value-of select="DE[1]/DEn_0"/></xsl:variable>
		
		String selection = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{4}\\().+", defStringToConvert); //grabs string from start ( to end
		selection = selection.substring(0, selection.length()-1); //gets rid of end )
		String numberOfSpaces = regexMatcher.getRegexMatch("[0-9]+(?=,)", selection);
		String padAsciiRepresentation = regexMatcher.getRegexMatch("(?<=\",)[0-9]+", selection);
		String auxiliary = regexMatcher.getRegexMatch("(?<=" + numberOfSpaces + ",\").+(?=\"," + padAsciiRepresentation + ")", selection);
		String auxiliaryVariableName = getNextTempVariableName("padl", 1).substring(1); //substring to get rid of $
		NewConverter DEFConverter = new NewConverter();
		DEFConverter.convert(auxiliary);
		String result = DEFConverter.resultVariables + DEFConverter.resultXSL;
		return wrapVariable(result, auxiliaryVariableName);
	}
	
	public static String convertDateMathToXSL(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@DATEMATH(@DE1:18",3,2,1)"
		// output: 
		//			<xsl:value-of select="mismo:cOneDATEMATH(mismo:getDateFromMMDDYYYY($datemath0),3,2,1)"/>"/>
		
		String selection = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{8}\\().+(?=\\))", defStringToConvert);
		String days = regexMatcher.getRegexMatch("(?<=,)[0-9]+(?=,)", selection);
		String months = regexMatcher.getRegexMatch("(?<=," + days +",)[0-9]+(?=,)", selection);
		String years = regexMatcher.getRegexMatch("(?<=," + days +"," + months +",)[0-9]+", selection);
		String tempDateToChangeVariable = getNextTempVariableName("datemath", 0);
		String returnString = wrapInXSL("mismo:cOneDATEMATH(mismo:getDateFromMMDDYYYY(" + tempDateToChangeVariable + "), " + days + ", " + months + ", " + years + ")");
		return returnString;
	}
	
	public static String getDateMathVariables(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@DATEMATH(@DE1:18",3,2,1)"
		// output: 
		//			<xsl:variable name="datemath0"><xsl:value-of select="DE[1]/DEn_18"/></xsl:variable>
		
		String variableSelection = regexMatcher.getRegexMatch("(?<=\\().+(?=,)", defStringToConvert);
		NewConverter DEFConverter = new NewConverter();
		DEFConverter.convert(variableSelection);
		String result = DEFConverter.resultXSL;
		return wrapAndNameVariable(result, "datemath");
	}
	
	public static String convertLiteralToXSL(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "hello. this is text"
		//			defStringToConvert = "`test`"
		// output: 
		//			<xsl:value-of select="'hello. this is text'"/>
		//			<xsl:value-of select="'test'"/>
		
		String returnString = regexMatcher.getRegexMatch("[^@\\(\\[\\]\\)]+", defStringToConvert);
		returnString = returnString.replaceAll("[`]", ""); //gets rid of any ` characters
		if (!(isNumber(returnString))) { //if it isn't a number then surround return string with '
			returnString = "'" + returnString + "'"; //'returnString'
		}
		return wrapInXSL(returnString);
	}
	
	private static boolean isNumber(String stringThatIsPotentiallyNumber) {
		// input:
		//			stringThatIsPotentialNumber = "92"
		//			stringThatIsPotentialNumber = "hell0 th3r3"
		// output:
		//			true
		//			false
		boolean onlyNumbers = true;
		for (int i=0; i<stringThatIsPotentiallyNumber.length(); i++) {
			if (!(Character.isDigit(stringThatIsPotentiallyNumber.charAt(i)))) {
				onlyNumbers = false;
			}
		}
		return onlyNumbers;
	}
	
	public static String convertMathToXSL(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@MATH("(@DE1:18 + 4)/(2*@DE:5)")"
		// output: 
		//			<xsl:value-of select="($math0 + $math1) div ($math2 * $math3)"/>
		
		String spacelessDefStringToConvert = removeSpaces(defStringToConvert);
		String selection = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{4}\\(\").+", spacelessDefStringToConvert);
		selection = selection.substring(0, selection.length()-2); //gets rid of end ")
		String returnString = "";
		for (int i=0; i<selection.length(); i++) {
			boolean didMatch = false; //used to skip the else statement if a match has already been found
			if (selection.charAt(i) == '(') { //if a ( add a ( to the returned string and say a match has been made
				returnString += "(";
				didMatch = true; 
			}
			if (selection.charAt(i) == ')') { //if a ) add a ) to the returned string and say a match has been made
				returnString += ")";
				didMatch = true;
			}
			//if an operand add the converted operand to the returned string and say a match has been made
			if (selection.charAt(i) == '+' || selection.charAt(i) == '-' || selection.charAt(i) == '*' || selection.charAt(i) == '/') {
				returnString += convertOperands(selection.charAt(i));
				didMatch = true;
			}
			else { //catches everything that is not a number if no match has yet been made and adds a temporary variable to the returned string
				if (!didMatch) {
					//sets the appropriate value of i according to the length of the math piece
					//while the next current character is not an operand or parentheses increment i
					//i+1 because i++ is called at the beginning of the for statement, therefore needs to be called here one less time
					//selection.length() != i+1 to avoid index out of bounds exceptions
					while ((selection.length() != i+1) && (selection.charAt(i+1) != '(') && (selection.charAt(i+1) != ')') && (selection.charAt(i+1) != '+') && (selection.charAt(i+1) != '-') && (selection.charAt(i+1) != '*' && (selection.charAt(i+1) != '/'))) {
					i++;
					}
					//adds the temporary variable name, to be defined in the variable pass
					returnString += getNextTempVariableName("math", 0);
				}
			}
		}		
		return wrapInXSL(returnString);
	}
	
	public static String getMathVariables(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "@MATH("(@DE1:18 + 4)/(2*@DE1:5)")"
		// output: 
		//			<xsl:variable name="math0"><xsl:value-of select="DE[1]/DEn_18"/></xsl:variable><xsl:variable name="math1"><xsl:value-of select="4"/></xsl:variable><xsl:variable name="math2"><xsl:value-of select="2"/></xsl:variable><xsl:variable name="math3"><xsl:value-of select="DE[1]/DEn_5"/></xsl:variable>
		
		String spacelessDefStringToConvert = removeSpaces(defStringToConvert);
		String selection = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{4}\\(\").+", spacelessDefStringToConvert);
		selection = selection.substring(0, selection.length()-2); //gets rid of end ")
		String returnString = "";
		for (int i=0; i<selection.length(); i++) {
			boolean didMatch = false; //used to skip the else statement if a match has already been found
			if (selection.charAt(i) == '(') { //if a ( add a ( to the returned string and say a match has been made
				didMatch = true; 
			}
			if (selection.charAt(i) == ')') { //if a ) add a ) to the returned string and say a match has been made
				didMatch = true;
			}
			//if an operand add the converted operand to the returned string and say a match has been made
			if (selection.charAt(i) == '+' || selection.charAt(i) == '-' || selection.charAt(i) == '*' || selection.charAt(i) == '/') {
				didMatch = true;
			}
			else { //catches everything that is not a number if no match has yet been made and adds a temporary variable to the returned string
				if (!didMatch) {
					//sets the appropriate value of i according to the length of the math piece
					//while the next current character is not an operand or parentheses increment i
					//i+1 because i++ is called at the beginning of the for statement, therefore needs to be called here one less time
					//selection.length() != i+1 to avoid index out of bounds exceptions
					int oldI = i;
					while ((selection.length() != i+1) && (selection.charAt(i+1) != '(') && (selection.charAt(i+1) != ')') && (selection.charAt(i+1) != '+') && (selection.charAt(i+1) != '-') && (selection.charAt(i+1) != '*' && (selection.charAt(i+1) != '/'))) {
					i++;
					}
					NewConverter newConverter = new NewConverter();
					newConverter.convert(selection.substring(oldI, i+1));
					returnString += wrapAndNameVariable(newConverter.resultXSL, "math");
			}
			}
		}		
		return returnString;
	}
	
	public static String convertFmtToXSL(String defStringToConvert) {
		// input:
		// 			1. defStringToConvert = "@FMT("@DE1:18","mmmm dd, yyyy")"
		//			2. defStringToConvert = "@FMT("@DE1:18","$###,00")"
		// output: 
		//			1. <xsl:value-of select="format-date(mismo:convertToDate($fmt0),'[MNn] [D01], [Y0001]')"/>
		//			2. <xsl:value-of select="format-number($fmt0,'$###,00')"/>
		
		String selection = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{3}\\().+", defStringToConvert);
		selection = selection.substring(0, selection.length()-1); //gets rid of end )
		String tempAuxiliaryVariable = getNextTempVariableName("fmt", 0);
		//int numberOfDoubleQuotes = getNumberOfDoubleQuotesInString(selection);
		String formatPattern = selection.substring(getIndexOfXToLastDoubleQuote(selection, 2)-1, selection.length());
		formatPattern = convertFormatPattern(formatPattern);
		String returnString = "";
		
		String formatType = getFormatType(formatPattern);
		if (formatType == "number") {
			returnString = wrapInXSL("format-number(" + tempAuxiliaryVariable + "," + formatPattern + ")");
		}
		else if (formatType == "date") {
			returnString = wrapInXSL("format-date(mismo:convertToDate(" + tempAuxiliaryVariable + ")," + formatPattern + ")");
		}
		return returnString;
	}
	
	public static String getFmtVariables(String defStringToConvert) {
		// input:
		// 			1. defStringToConvert = "@FMT("@DE1:18","mmmm dd, yyyy")"
		//			2. defStringToConvert = "@FMT("@DE1:18","$###,00")"
		// output: 
		//			1. <xsl:variable name="fmt0"><xsl:value-of select="DE[1]/DEn_18"/></xsl:variable>
		//			2. <xsl:variable name="fmt0"><xsl:value-of select="DE[1]/DEn_18"/></xsl:variable>
		
		String selection = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{3}\\().+", defStringToConvert);
		selection = selection.substring(1, getIndexOfXToLastDoubleQuote(selection, 3)-1); //1 gets rid of start ", goes to end "
		String tempVariable = getNextTempVariableName("fmt", 1); //called before DEFConverter.convert()
		NewConverter DEFConverter = new NewConverter();
		DEFConverter.convert(selection);
		String result = DEFConverter.resultVariables + DEFConverter.resultXSL;
		System.out.println(wrapVariable(result, tempVariable.substring(1)));
		return wrapVariable(result, tempVariable.substring(1)); //1 gets rid of $
	}
	
	private static String getFormatType(String undeterminedFormat) {
		// input:
		// 			1. undeterminedFormat = "mmmm dd, yyyy"
		//			2. undeterminedFormat = "$###,00"
		// output: 
		//			1. '[MNn] [D01], [Y0001]'
		//			2. '$###,00'
		
		String formatType = "";
		boolean matchesAsANumber = false;
		boolean matchesAsADate = false;
		for (int i=0; i<undeterminedFormat.length(); i++) {
			if (undeterminedFormat.charAt(i) == '#') {
				matchesAsANumber = true;
			}
			else if (undeterminedFormat.charAt(i) == 'M' || undeterminedFormat.charAt(i) == 'D' || undeterminedFormat.charAt(i) == 'Y') {
				matchesAsADate = true;
			}
		}
		if (matchesAsANumber && !matchesAsADate) {
			formatType = "number";
		}
		else if (matchesAsADate && !matchesAsANumber) {
			formatType = "date";
		}
		else {
			formatType = "invalid format";
		}
		return formatType;
	}

	public static String convertIfToXSL(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "[(@AP:1=`2` AND @AP:3>`4`){@AP:5}]"
		//
		// output: 
		//			<xsl:if test="$if0 = $if1 and $if2 &gt; $if3"><xsl:value-of select="$if4"/></xsl:if> 
		
		String selection = regexMatcher.getRegexMatch("(?<=\\[\\().+", defStringToConvert); //grabs string from start ( to end
		String conditional = getCharactersUntilFinalCloseParathesis(selection); // grabs conditional
		String returnString = "<xsl:if test='";
		returnString += convertConditionalToXSL(conditional, "if");
		returnString += "'>"
				//adds a single variable for the output
		+ wrapInXSL("$" + getNextTempVariableName("if", 0).substring(1)) //to get rid of $ at front of name
		+ "</xsl:if>";
		return returnString;
	}
	
	private static String convertConditionSign(String conditionSign) {
		//	input: (see below for all possibilities)
		//			conditionSign = "<>"
		//			conditionSign = ">="
		//			conditionSign = "<"
		//	output:
		//			" != "
		//			" &gt;= "
		//			" &lt; "
		//
		//It appears to be that xsl evaluates conditions in reverse
		//e.g. a < b returns true if b < a
		String returnString = "";
		if (conditionSign.charAt(0) == '<') { // if either < <= or <>
			if (conditionSign.length() == 2) { //if either <= or <>
				if (conditionSign.charAt(1) == '>') { //if <>
					returnString = " != ";			  //return ' != '
				} else {							  //if <=
					returnString = "*1 &lt;= ";		  //return ' &lt;= '
				}
			} else {								  //if <
				returnString = "*1 &lt; ";			  //return ' &lt; '
			}
		} else if (conditionSign.charAt(0) == '>') {  //if > or >=
			if (conditionSign.length() == 2) {		  //if >=
				returnString = "*1 &gt;= ";			  //return ' &gt;= '
			} else {								  //if >
				returnString = "*1 &gt; ";			  //return ' &gt; '
			}
		} else if (conditionSign.charAt(0) == '=') {  //if =
			returnString = " = ";					  //return ' = '
		}
		return returnString;
	}
	
	private static String getCharactersUntilFinalCloseParathesis(String selection) {
		// input:
		// 			selection = "(hello(hit)here){more stuff to ignore )(())(}"
		// output: 
		//			'hello(hit)here'
		
		String stringToReturn = "";
		int currentCharIndex = 0;
		int countOfOpenParatheses = 0;
		while (currentCharIndex < selection.length() && (selection.charAt(currentCharIndex) != ')' || countOfOpenParatheses > 1 )) { 
			//if current character is not ')' 
			//or if it is ')' and there is only one open parentheses that has yet to be closed
			stringToReturn += selection.charAt(currentCharIndex);
			if(selection.charAt(currentCharIndex) == '(') countOfOpenParatheses++;
			if(selection.charAt(currentCharIndex) == ')') countOfOpenParatheses--;
			currentCharIndex++;
		}
		if (stringToReturn.charAt(0) == '(') {
			stringToReturn = stringToReturn.substring(1);
		}
		return stringToReturn; //gets rid of starting '('
	}
	
	private static String convertConditionalToXSL(String conditional, String varName) {
		//	input:
		//			conditional = "@AP$:13>5OR@AP$:12=`A`"
		//			varName = "if"
		//	output:	
		//			$loop0 &gt; $loop1 or $loop2 = $loop3	
		String returnString = "";
		int i=0;
		for (; i<conditional.length(); i++) {
			boolean didMatch = false; //used to skip the else statement if a match has already been found
			//if it is any condition sign e.g. <, >, <=, >=, <>, =  then add the converted condition sign to the returned string 
			if (conditional.charAt(i) == '<' || conditional.charAt(i) == '>' || conditional.charAt(i) == '=') {
				didMatch = true;
				String conditionSign = getConditionSign(conditional.substring(i)); //returns the specified conditional i.e. < > <= >= == <> !=
				returnString += convertConditionSign(conditionSign); //adds the converted condition sign to the return string
				if (conditionSign.length() > 1) { //skips the rest of the conditionSign if necessary
					i += conditionSign.length() - 1; //i-1 because i is incremented at the beginning of the loop
				}
			}
			//if it is AND or OR then add " and "   or   " or ", respectively, to the returned string and skip the rest of its characters
			String andOr = getAndOr(conditional.substring(i)); //returns null if not AND or OR
			if (andOr != null) {
				didMatch = true;
				returnString += " " + andOr.toLowerCase() + " ";
				i += andOr.length()-1;
			}
			else {
				if (!didMatch) { //catches everything else
					//sets the appropriate value of i according to the length of the if piece
					//while the next current character is not a condition sign, AND, or OR increment i
					//i+1 because i++ is called at the beginning of the for statement, therefore needs to be called here one less time
					//selection.length() != i+1 to avoid index out of bounds exceptions
					while ((conditional.length() != i+1) && (getAndOr(conditional.substring(i+1)) == null) && (getConditionSign(conditional.substring(i+1)) == null)) {
						i++;
					}
					//adds the temporary variable name, to be defined in the variable pass
					returnString += getNextTempVariableName(varName, 0);
				}
			}
		}
		return returnString;
	}

	private static String getConditionalVariables(String conditional, String varName) {
		//		input:
		//			conditional = "@AP$:13>5OR@AP$:12=`A`"
		//			varName = "if"
		//	output:	
		//			<xsl:variable name="loop0"><xsl:value-of select="APn_13"/></xsl:variable><xsl:variable name="loop1"><xsl:value-of select="5"/></xsl:variable><xsl:variable name="loop2"><xsl:value-of select="APn_12"/></xsl:variable><xsl:variable name="loop3"><xsl:value-of select="'A'"/></xsl:variable>
		String returnString = "";
		int i=0;
		for (; i<conditional.length(); i++) {
			boolean didMatch = false; //used to skip the else statement if a match has already been found
			//if it is any condition sign e.g. <, >, <=, >=, <>, =  then add the converted condition sign to the returned string 
			if (conditional.charAt(i) == '<' || conditional.charAt(i) == '>' || conditional.charAt(i) == '=') {
				didMatch = true;
				String conditionSign = getConditionSign(conditional.substring(i)); //returns the specified conditional i.e. < > <= >= == <> !=
				if (conditionSign.length() > 1) { //skips the rest of the conditionSign if necessary
					i += conditionSign.length() - 1; //i-1 because i is incremented at the beginning of the loop
				}
			}
			//if it is AND or OR then add " and "   or   " or ", respectively, to the returned string and skip the rest of its characters
			String andOr = getAndOr(conditional.substring(i)); //returns null if not AND or OR
			if (andOr != null) {
				didMatch = true;				
				i += andOr.length()-1; //i-1 because i is incremented at the beginning of the loop
			}
			else {
				if (!didMatch) { //catches everything else
					//sets the appropriate value of i according to the length of the if piece
					//while the next current character is not a condition sign, AND, or OR increment i
					//i+1 because i++ is called at the beginning of the for statement, therefore needs to be called here one less time
					//selection.length() != i+1 to avoid index out of bounds exceptions
					int oldI = i;
					while ((conditional.length() != i+1) && (getAndOr(conditional.substring(i+1)) == null) && (getConditionSign(conditional.substring(i+1)) == null)) {
						i++;
					}
					//convert the if piece
					NewConverter nc = new NewConverter();
					nc.convert(conditional.substring(oldI, i+1)); //i+1 due to the nature of substring(int, int)
					//adds the variable to the return string
					returnString += wrapAndNameVariable(nc.resultXSL, varName);
				}
			}
		}
		return returnString;
	}
	
	public static String getIfVariables(String defStringToConvert) {
		// input:
		// 			defStringToConvert = "[(@AP:1=`2` AND @AP:3>`4`){@AP:5}]"
		// output: 
		//			<xsl:variable name="if0"><xsl:value-of select="AP_1"/></xsl:variable><xsl:variable name="if1"><xsl:value-of select="2"/></xsl:variable><xsl:variable name="if2"><xsl:value-of select="AP_3"/></xsl:variable><xsl:variable name="if3"><xsl:value-of select="4"/></xsl:variable><xsl:variable name="if4"><xsl:value-of select="AP_5"/></xsl:variable>
		
		String selection = regexMatcher.getRegexMatch("(?<=\\[\\().+", defStringToConvert); //grabs string from start ( to end
		String conditional = getCharactersUntilFinalCloseParathesis(selection); // grabs conditional
		conditional = removeSpaces(conditional); // removes all spaces from the conditional
		String output = regexMatcher.getRegexMatch("(?<=\\{).+(?=\\})", selection); // grabs output
		NewConverter newConverter = new NewConverter();
		newConverter.convert(output); //converts the output between { and }
		String returnString = newConverter.resultVariables //adds any variables the output needs to the return string; done early for aesthetics
		+ getConditionalVariables(conditional, "if");
		returnString += wrapAndNameVariable(newConverter.resultXSL, "if"); //adds one last variable which contains the resultXSL from the output between { and }
		return returnString;
	}	
	
	public static String convertLoopToXSL(String defStringToConvert) {
		// input:  
		// 			defStringToConvert = "[$LOOP:AP(@AP$:13>5 OR @AP$:12=`A`){hello this works with @AP$:13}]"
		// output: 
		//			<xsl:for-each select='AP'>
		//				<xsl:variable name="loop0"><xsl:value-of select="APn_13"/></xsl:variable>
		//				<xsl:variable name="loop1"><xsl:value-of select="5"/></xsl:variable>
		//				<xsl:variable name="loop2"><xsl:value-of select="APn_12"/></xsl:variable>
		//				<xsl:variable name="loop3"><xsl:value-of select="'A'"/></xsl:variable>
		//				<xsl:variable name="loop4">
		//					<xsl:value-of select="'hello this works with '"/>
		//					<xsl:value-of select="APn_13"/>
		//				</xsl:variable>
		//				<xsl:if select='$loop0 &gt; $loop1 or $loop2 = $loop3'><xsl:value-of select="$loop4"/></xsl:if>
		//			</xsl:for-each>
		
		//This method manually calls the getLoopVariablesDuringXslCall method
		//due to the dependency of loops on looped variables
		//the xsl and variables cannot be independent in converted loops
		String selection = regexMatcher.getRegexMatch("(?<=\\[\\$[L|l][O|o][O|o][P|p]:).+", defStringToConvert); //grabs string from start ( to end
		String loopedEntryAA = selection.substring(0, 2); //grabs the two letters that are looped e.g. AP, FE, etc.
		selection = selection.substring(2); //removes the two aforementioned letters from the selection string
		String conditional = getCharactersUntilFinalCloseParathesis(selection); // grabs conditional
		conditional = removeSpaces(conditional);
		String returnString = "<xsl:for-each select='"
		+ loopedEntryAA
		+ "'>"
		+ getLoopVariablesFromXslCall(selection, conditional)
		+ "<xsl:if test='"
		+ convertConditionalToXSL(conditional, "loop") //converts the conditional to an xsl selection of variables, operands, and 'and/or's
		+ "'>"
		//adds a single variable for the output
		+ wrapInXSL("$" + getNextTempVariableName("loop", 0).substring(1)) //to get rid of $ at front of name
		+ "</xsl:if></xsl:for-each>";
		return returnString;
	}
	
	public static String getLoopVariablesFromXslCall(String selection, String conditional) {
		// input:  
		// 			defStringToConvert = "[$LOOP:AP(@AP$:13>5 OR @AP$:12=`A`){hello this works with @AP$:13}]"
		// output: 
		//			<xsl:variable name="loop0"><xsl:value-of select="APn_13"/></xsl:variable>
		//			<xsl:variable name="loop1"><xsl:value-of select="5"/></xsl:variable>
		//			<xsl:variable name="loop2"><xsl:value-of select="APn_12"/></xsl:variable>
		//			<xsl:variable name="loop3"><xsl:value-of select="'A'"/></xsl:variable>
		//			<xsl:variable name="loop4">
		//				<xsl:value-of select="'hello this works with '"/>
		//				<xsl:value-of select="APn_13"/>
		//			</xsl:variable>
		String output = regexMatcher.getRegexMatch("(?<=\\{).+(?=\\})", selection); // grabs output from selection
		NewConverter newConverter = new NewConverter();
		newConverter.convert(output); //converts the output between { and }
		String returnString = newConverter.resultVariables //adds any variables the output needs to the return string; done early for aesthetics
		+ getConditionalVariables(conditional, "loop") //converts the conditional to an xsl selection of variables, operands, and 'and/or's
		+ wrapAndNameVariable(newConverter.resultXSL, "loop"); //adds one last variable which contains the resultXSL from the output between { and }
		System.out.println(returnString);
		return returnString;
	}
	
	public static String getLoopVariables(String defStringToConvert) {
		return "";
	}
	
	private static String getAndOr(String stringWithPotentialAndOr) {
		//	input:
		//			stringWithPotentialAndOr = "AP:1=`2`"
		//			stringWithPotentialAndOr = "AND @AP:1 > 1"
		//			stringWithPotentialAndOr = "OR @AP:1 > 1"
		//	output:
		//			null
		//			AND
		//			OR
		String returnString = null;
		String regexANDMatch = regexMatcher.getRegexMatch("[A|a][N|n][D|d]", stringWithPotentialAndOr);
		String regexORMatch = regexMatcher.getRegexMatch("[O|o][R|r]", stringWithPotentialAndOr);
		if (stringWithPotentialAndOr.length() >= 3 &&  regexANDMatch != null && regexANDMatch.equals(stringWithPotentialAndOr.substring(0, 3))) {
			returnString = "AND";
		}
		else if (stringWithPotentialAndOr.length() >= 2 &&  regexORMatch != null && regexORMatch.equals(stringWithPotentialAndOr.substring(0, 2))) {
			returnString = "OR";
		}
		return returnString;
	}
	
	private static String getConditionSign(String stringWithConditionSign) {
		//	input:
		//			stringWithConditionSign = "=`2`"
		//			stringWithConditionSign = ">= 1"
		//	output:
		//			"="
		//			">="
		String returnString = null;
		int i=0;
		//goes through every character in stringWithConditionSign and increments i every character 
		//stops when the character at i is not '<' '>' or '='
		for (; i<stringWithConditionSign.length() && (stringWithConditionSign.charAt(i) == '=' || stringWithConditionSign.charAt(i) == '<' || stringWithConditionSign.charAt(i) == '>'); i++) {	}
		if (i != 0) {
			returnString = stringWithConditionSign.substring(0, i); //substrings the condition sign off of the original string
		}
		return returnString;
	}

	private static String convertFormatPattern(String defFormatPattern) {
		//	input:
		//			defFormatPattern = "mm/dd/yyyy"
		//	output:
		//			[M01]/[D01]/[Y0001]
		String xmlFormatPattern = "";
		for (int i=0; i<defFormatPattern.length(); i++) {
			if (defFormatPattern.charAt(i) == '\"') {
				xmlFormatPattern += "'";
			}
			else if (defFormatPattern.charAt(i) == 'y') {
				String s = "[Y";
				int j;
				for (j=i; j<defFormatPattern.length() && defFormatPattern.charAt(j) == 'y'; j++) {
					s += "0";
				}
				s = s.substring(0, s.length()-1);
				s += "1]";
				i = j-1;
				xmlFormatPattern += s;
			}
			else if (defFormatPattern.charAt(i) == 'm') {
				String s = "";
				int numberOfMs = 0;
				int j;
				for (j=i; j<defFormatPattern.length() && defFormatPattern.charAt(j) == 'm'; j++) {
					numberOfMs++;
				}
				if (numberOfMs == 1) {
					s = "[M1]";
				}
				else if (numberOfMs == 2) {
					s = "[M01]";
				}
				else if (numberOfMs == 3) {
					s = "[MNn*-3]";
				}
				else if (numberOfMs == 4) {
					s = "[MNn]";
				}
				i = j-1;
				xmlFormatPattern += s;
			}
			else if (defFormatPattern.charAt(i) == 'd') {
				String s = "";
				int numberOfDs = 0;
				int j;
				for (j=i; j<defFormatPattern.length() && defFormatPattern.charAt(j) == 'd'; j++) {
					numberOfDs++;
				}
				if (numberOfDs == 1) {
					s = "[D1]";
				}
				else if (numberOfDs == 2) {
					s = "[D01]";
				}
				i = j-1;
				xmlFormatPattern += s;
			}
			else {
				xmlFormatPattern += defFormatPattern.charAt(i);
			}
		}
		return xmlFormatPattern;
	}
	
	private static int getIndexOfXToLastDoubleQuote(String stringWithDoubleQuotes, int x) {
		//	input:
		//			stringWithDoubleQuotes = hello"there".I am full of "quotes"
		//			int x = 2
		//	output:
		//			26
		int numberOfDoubleQuotes = getNumberOfDoubleQuotesInString(stringWithDoubleQuotes);
		int currentCharacterIndex;
		for (currentCharacterIndex=0; currentCharacterIndex<stringWithDoubleQuotes.length() && ((numberOfDoubleQuotes-x+1) != 0); currentCharacterIndex++) {
			if (stringWithDoubleQuotes.charAt(currentCharacterIndex) == '\"') {
				numberOfDoubleQuotes--;
			}
		}
		return currentCharacterIndex;
	}
	
	private static int getNumberOfDoubleQuotesInString(String stringWithDoubleQuotes) {
		//	input:
		//			stringWithDoubleQuotes = hello"there". I am full of "quotes"
		//	output:
		//			4
		int numberOfDoubleQuotes = 0;
		for (int i=0; i<stringWithDoubleQuotes.length(); i++) {
			if (stringWithDoubleQuotes.charAt(i) == '\"') {
				numberOfDoubleQuotes++;
			}
		}
		return numberOfDoubleQuotes;
	}

	private static String convertOperands(char group) {
		//	input:
		//			group = '-'
		//			group = '/'
		//	output:
		//			" - "
		//			" div "
		String returnString = "";
		if (group == '+') {
			returnString = " + ";
		} else if (group == '-') {
			returnString = " - ";
		} else if (group == '*') {
			returnString = " * ";
		} else if (group == '/') {
			returnString = " div ";
		}

		return returnString;
	}

	private static String removeSpaces(String stringWithSpaces) {
		//	input:
		//			stringWithSpaces = "this is a string with spaces"
		//	output:
		//			"thisisastringwithspaces"
		String returnString = "";
		for (int i = 0; i < stringWithSpaces.length(); i++) {
			if (!Character.isSpaceChar(stringWithSpaces.charAt(i))) {
				returnString = returnString.concat(String.valueOf(stringWithSpaces.charAt(i)));
			}
		}
		return returnString;
	}

	private static String getNextTempVariableName(String nameOfVar, int runNumber) { //run 0 is XSL, 1 is Variable
		//	input:
		//			nameOfVar = "padl"
		//			runNumber = 0
		//	output:
		//			$padl2
		String returnString = "";
		if (runNumber == 0) {
			XSLRunVariableIndex++;
			returnString = "$" + nameOfVar + (XSLRunVariableIndex - 1);
		}
		else {
			VariableRunVariableIndex++;
			returnString = "$" + nameOfVar + (VariableRunVariableIndex - 1);
		}
		return returnString;
	}
	
	private static String wrapAndNameVariable(String contentsOfVariable, String nameOfVariable) {
		//	input:
		//			contentsOfVariable = "<xsl:value-of select="AP[1]/APn_3"/>"
		//			nameOfVariable = "if"
		//	output:
		//			<xsl:variable name="if1"><xsl:value-of select="AP[1]/APn_3"/></xsl:variable>
		VariableRunVariableIndex++;
		return "<xsl:variable name=\"" + nameOfVariable + (VariableRunVariableIndex-1) + "\">" + contentsOfVariable + "</xsl:variable>";
	}
	
	private static String wrapVariable(String contentsOfVariable, String nameOfVariable) {
		//	input:
		//			contentsOfVariable = "<xsl:value-of select="AP[1]/APn_3"/>"
		//			nameOfVariable = "if2"
		//	output:
		//			<xsl:variable name="if2"><xsl:value-of select="AP[1]/APn_3"/></xsl:variable>
		return "<xsl:variable name=\"" + nameOfVariable + "\">" + contentsOfVariable + "</xsl:variable>";
	}
	
	public static String convertA_xToXSL(String defStringToConvert) 
	{
		//	input:
		//			defStringToConvert = @AP:2
		//	output:
		//			<xsl:value-of select="AP_2"/>
		String convString = "";
		//Get first two letters between @ and :
		String firstTwoLettersOfAPVariable = regexMatcher.getRegexMatch("(?<=@)[a-zA-Z]{2,}(?=:)", defStringToConvert);
		//Get first set of numbers after :
		String numbersAfterColon = regexMatcher.getRegexMatch("(?<=:)[0-9]+", defStringToConvert);
		convString = convString + firstTwoLettersOfAPVariable;
		convString = convString + "_";
		convString = convString + numbersAfterColon;
		convString = wrapInXSL(convString);

		return convString;
	}
	
	public static String convertAx_xToXSL(String defStringToConvert)
	{
		//	input:
		//			defStringToConvert = @AP1:2
		//	output:
		//			<xsl:value-of select="AP[1]/APn_2"/>
		String convString = "";
		String idLetters = regexMatcher.getRegexMatch("(?<=@)[A-Za-z]{2}", defStringToConvert);
		String idNumsA = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2})\\d{1,4}", defStringToConvert);
		String idNumsB = regexMatcher.getRegexMatch("(?<=:)\\d{1,4}", defStringToConvert);
		
		convString = convString.concat(idLetters + "[" + idNumsA + "]/" + idLetters + "n_" + idNumsB);
		convString = wrapInXSL(convString);
		
		return convString;
	}
	
	public static String convertA_A_xToXSL(String defStringToConvert) {
		//	input:
		//			defStringToConvert = "@DE:DF:1"
		//	output:
		//			<xsl:value-of select="DE_DF/DE_DFn_1"/>
		String convString = "";
		String idLettersA = regexMatcher.getRegexMatch("(?<=@)[A-Za-z]{2}", defStringToConvert);
		String idLettersB = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}:)[A-Za-z]{2}", defStringToConvert);
		String idNums = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}:[A-Za-z]{2}:)\\d{1,4}", defStringToConvert);
		
		convString = convString.concat(idLettersA + "_" + idLettersB + "/" + idLettersA + "_" + idLettersB + "n_" + idNums);
		convString = wrapInXSL(convString);
		
		return convString;
	}
	
	public static String convertAx_A_xToXSL(String defStringToConvert) {
		//	input:
		//			defStringToConvert = "@DE1:DF:2"
		//	output:
		//			<xsl:value-of select="DE[1]_DF/DEn_DF_2"/>	
		String convString = "";
		String idLettersA = regexMatcher.getRegexMatch("(?<=@)[A-Za-z]{2}", defStringToConvert);
		String idLettersB = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}\\d{1,4}:)[A-Za-z]{2}", defStringToConvert);
		String idNumsA = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2})\\d{1,4}", defStringToConvert);
		String idNumsB = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}\\d{1,4}:[A-Za-z]{2}:)\\d{1,4}", defStringToConvert);
		
		convString = convString.concat(idLettersA + "[" + idNumsA + "]_" + idLettersB + "/" + idLettersA + "n_" + idLettersB + "_" + idNumsB);
		convString = wrapInXSL(convString);
		
		return convString;
	}
	
	public static String convertA_Ax_xToXSL(String defStringToConvert) {
		//	input:
		//			defStringToConvert = "@DE:DF1:2"
		//	output:
		//			<xsl:value-of select="DE_DF[1]/DE_DFn_2"/>		
		String convString = "";
		String idLettersA = regexMatcher.getRegexMatch("(?<=@)[A-Za-z]{2}", defStringToConvert);
		String idLettersB = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}:)[A-Za-z]{2}", defStringToConvert);
		String idNumsA = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}:[A-Za-z]{2})\\d{1,4}", defStringToConvert);
		String idNumsB = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}:[A-Za-z]{2}\\d{1,4}:)\\d{1,4}", defStringToConvert);
		
		convString = convString.concat(idLettersA + "_" + idLettersB + "[" + idNumsA + "]/" + idLettersA + "_" + idLettersB +"n_" + idNumsB);
		convString = wrapInXSL(convString);
		
		return convString;
	}
	
	public static String convertAx_Ax_xToXSL(String defStringToConvert) {
		//	input:
		//			defStringToConvert = "@DE1:DF2:3"
		//	output:
		//			<xsl:value-of select="DE[1]_DF[2]/DEn_DFn_3"/>		
		String convString = "";
		String idLettersA = regexMatcher.getRegexMatch("(?<=@)[A-Za-z]{2}", defStringToConvert);
		String idLettersB = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}\\d{1,4}:)[A-Za-z]{2}", defStringToConvert);
		String idNumsA = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2})\\d{1,4}", defStringToConvert);
		String idNumsB = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}\\d{1,4}:[A-Za-z]{2})\\d{1,4}", defStringToConvert);
		String idNumsC = regexMatcher.getRegexMatch("(?<=@[A-Za-z]{2}\\d{1,4}:[A-Za-z]{2}\\d{1,4}:)\\d{1,4}", defStringToConvert);
		
		convString = convString.concat(idLettersA + "[" + idNumsA + "]_" + idLettersB + "[" + idNumsB + "]/" + idLettersA + "n_" + idLettersB + "n_" + idNumsC);
		convString = wrapInXSL(convString);
		
		return convString;
	}
	
	public static String convertLoopVariableToXSL(String defStringToConvert) {
		//	input:
		//			defStringToConvert = "@FE$:1"
		//	output:
		//			<xsl:value-of select="FEn_1"/>		
		String convString = "";
		//Get first two letters between @ and $
		String firstTwoLettersOfAPVariable = regexMatcher.getRegexMatch("(?<=@)[a-zA-Z]{2,}(?=\\$)", defStringToConvert);
		//Get first set of numbers after $
		String numbersAfterDollarSign = regexMatcher.getRegexMatch("(?<=:)[0-9]+", defStringToConvert);
		convString = convString + firstTwoLettersOfAPVariable;
		convString = convString + "n_";
		convString = convString + numbersAfterDollarSign;
		convString = wrapInXSL(convString);

		return convString;
	}
	
	public static String convertNullToXSL(String defStringToConvert) {
		return wrapInXSL("''");
	}
	
	public static String wrapInXSL(String string) 
	{
		//	input:
		//			string = "'some plain text'"
		//	output:
		//			<xsl:value-of select="'some plain text'"/>
		String returnedString = "<xsl:value-of select=\"" + string + "\"/>";
		return returnedString;
	}

	public static Object getResultFromInvokedMethod(String method, String defStringToConvert) {
		//	input:
		//			method = "convertAx_XToXSL"
		//			defStringToConvert = "@DE1:2"
		//	output:
		//			<xsl:value-of select="AP[1]/APn_2"/>
		Object methodResult = null;
		if (method.isEmpty()) { //doesn't get xsl variables when converting def variables or nulls (no need)
			return "";
		} else {
			try {
				Method methodToInvoke = DEFfunctionConverters.class.getMethod(method, String.class);
				methodResult = methodToInvoke.invoke(methodToInvoke, defStringToConvert);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		return methodResult;
	}

}
